package eg.backend.manager.impl;

import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.springframework.beans.factory.annotation.Autowired;

import eg.backend.domain.Budget;
import eg.backend.domain.Dimension;
import eg.backend.domain.fly.BudgetStatus;
import eg.backend.manager.BudgetManager;
import eg.backend.manager.UserManager;
import eg.backend.repository.BudgetRepository;
import eg.backend.repository.DimensionRepository;
import eg.backend.repository.ExpenseRepository;
import eg.backend.util.StringUtil;

public class BudgetManagerImpl implements BudgetManager {
	@Autowired
	private BudgetRepository budgetRepository;
	@Autowired
	private DimensionRepository dimensionRepository;
	@Autowired
	private ExpenseRepository expenseRepository;
	@Autowired
	private UserManager userManager;
	
	public Map<String, Float> findCategoryBudgets(Dimension root, Date from,
			Date to) {
		Map<String, Float> map = new HashMap<String, Float>(); 
		String userId = userManager.getCurrentUserId();
		List<Dimension> categories = new ArrayList<Dimension>();
		categories.add(root);
		categories.addAll(dimensionRepository.findAvailByParent(root.getEncodedKey(), userId, userManager.getCurrentUsername()));
		List<String> categoryIds = new ArrayList<String>();
		for(Dimension c : categories)
			categoryIds.add(c.getEncodedKey());
		List<Budget> budgets = budgetRepository.findByCategories(categoryIds, from, to, userId);
		for(Budget budget : budgets) {
			String category = budget.getCategory();
			float amount = budget.getAmount();
			if(map.containsKey(category)) {
				map.put(category, map.get(category) + amount);
			} else {
				map.put(category, amount);
			}
		}
		return map;
	}

	public Map<String, BudgetStatus> findCategoryBudgetStatus(Dimension root,
			Date from, Date to) {
		Map<String, BudgetStatus> budgetStatusMap = new HashMap<String, BudgetStatus>();;
		Map<String, Float> budgetMap = this.findCategoryBudgets(root, from, to);
		
		String userId = userManager.getCurrentUserId();
		List<Dimension> categories = new ArrayList<Dimension>();
		categories.add(root);
		categories.addAll(dimensionRepository.findAvailByParent(root.getEncodedKey(), userId, userManager.getCurrentUsername()));
		List<String> categoryIds = new ArrayList<String>();
		for(Dimension item : categories)
			categoryIds.add(item.getEncodedKey());
		
		for(String key : budgetMap.keySet()) {
			float usedAmount = expenseRepository.getTotalOfCategory(categoryIds, from, to, userId).floatValue();
			budgetStatusMap.put(key, new BudgetStatus(budgetMap.get(key).floatValue(), usedAmount));
		}
		return budgetStatusMap;
	}

	public Budget getByTagName(String tagName, Date from, Date to) {
		return budgetRepository.getByTag(from, tagName, to, userManager.getCurrentUserId());
	}

	public BudgetStatus getBudgetStatusByTag(String tagName, Date from, Date to) {
		Budget budget = this.getByTagName(tagName, from, to);
		if(budget == null)
			return null;
		return new BudgetStatus(budget.getAmount(), expenseRepository.getTotalOfTag(from, tagName, to, userManager.getCurrentUserId()).floatValue());
	}
	
	public void update(List<Budget> budgets) {
		String userId = userManager.getCurrentUserId();
		for(Budget budget : budgets) {
			if(!StringUtil.isEmpty(budget.getTag())) {
				Budget old = budgetRepository.getByTag(budget.getBegin(), budget.getTag(), budget.getEnd(), userId);
				if(budget.getEncodedKey() == null || !budget.getEncodedKey().equals(old.getEncodedKey()))
					continue;
			} else {
				List<Budget> oldBudgets = budgetRepository.findByCategory(budget.getCategory(), budget.getBegin(), budget.getEnd(), userId);
				boolean duplicate = false;
				for(Budget old : oldBudgets) {
					if(budget.getEncodedKey() == null || !budget.getEncodedKey().equals(old.getEncodedKey())) {
						duplicate = true;
						break;
					}
				}
				if(duplicate) {
					continue;
				}
			}
	
			budgetRepository.save(budget);
		}
	}

}
